/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.j4sc.submission;

/**
 * The MultiPartMimeBodyBuilder is used to construct the multi part MIME body of
 * the HTTP request used to submit a submission. As such it is not intended to
 * be used by end users of the API.
 * 
 * @author Raj Patel, Dariusz Lorenc
 */
public class MultiPartMimeBodyBuilder {

    public static final String MIME_BOUNDARY = "simpleboundary";

    private static final String BOUNDARY_INDICATOR = "--";
    private static final String HEADER_VALUE_SEPARATOR = ": ";
    private static final String CRLF = "\r\n";

    private final StringBuilder body;

    enum Header {
        CONTENT_TYPE("Content-Type"), CONTENT_LENGTH("Content-Length"), CONTENT_TRANSFER_ENCODING(
                "Content-Transfer-Encoding");

        private final String headerName;

        private Header(String headerName) {
            this.headerName = headerName;
        }

        String getHeaderName() {
            return headerName;
        }
    }

    MultiPartMimeBodyBuilder() {
        this.body = new StringBuilder();
    }

    MultiPartMimeBodyBuilder addPart() {
        startOfBoundary();
        terminateLine();
        return this;
    }

    MultiPartMimeBodyBuilder withHeader(Header header, String value) {
        addHeader(header, value);
        return this;
    }

    MultiPartMimeBodyBuilder withContent(String content) {
        String contentWithProperLineEnds = ensureProperLineEnds(content);
        addHeader(Header.CONTENT_LENGTH, String.valueOf(contentWithProperLineEnds.length()));
        terminateLine();
        body.append(contentWithProperLineEnds);
        if (!contentWithProperLineEnds.endsWith(CRLF)) {
            terminateLine();
        }
        terminateLine();
        return this;
    }

    private String ensureProperLineEnds(String content) {
        return content.replaceAll("[\r]?\n", CRLF);
    }

    String toBody() {
        startOfBoundary();
        addBoundaryIndicator();
        return body.toString();
    }

    private void addHeader(Header header, String value) {
        body.append(header.getHeaderName());
        body.append(HEADER_VALUE_SEPARATOR);
        body.append(value);
        terminateLine();
    }

    private void startOfBoundary() {
        addBoundaryIndicator();
        body.append(MIME_BOUNDARY);
    }

    private void addBoundaryIndicator() {
        body.append(BOUNDARY_INDICATOR);
    }

    private void terminateLine() {
        body.append(CRLF);
    }
}
